package org.harsh.transmission.server;

import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysDeptService;
import io.jpower.kcp.netty.UkcpChannel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.timeout.IdleStateHandler;
import io.netty.handler.traffic.ChannelTrafficShapingHandler;
import lombok.extern.slf4j.Slf4j;
import org.harsh.dispatch.CommVars;
import org.harsh.transmission.common.*;
import org.harsh.transmission.common.codec.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.net.InetSocketAddress;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component
public class KcpServerChannelInitilizer extends ChannelInitializer<UkcpChannel> {
    @Autowired
    private PlainMsgCodec plainMsgCodec;
    @Autowired
    private FileMsgCodec fileMsgCodec;
    @Autowired
    private ISysConfigService sysConfigService;
    @Autowired
    private ISysDeptService sysDeptService;
    /**
     * kcp
     * @param ukcpChannel
     * @throws Exception
     */
    @Override
    protected void initChannel(UkcpChannel ukcpChannel) throws Exception {
        long channelWriteLimit = 16384l;
        long channelReadLimit = 16384l;
        String tmpWriteStr = sysConfigService.selectConfigByKey("trans.write.channelLimit");
        String tmpReadStr = sysConfigService.selectConfigByKey("trans.read.channelLimit");
        if(tmpWriteStr != null)
            channelWriteLimit = Long.valueOf(tmpWriteStr);
        if(tmpReadStr != null)
            channelReadLimit = Long.valueOf(tmpReadStr);

        ChannelPipeline p = ukcpChannel.pipeline();
        p.addLast(GlobalTraffic.getInstance())
                .addLast("channelTraffic", new ChannelTrafficShapingHandler(channelWriteLimit, channelReadLimit, 1))
                .addLast(new IdleStateHandler(30, 0, 0, TimeUnit.SECONDS))
                .addLast(new LengthFieldBasedFrameDecoder(14000, 0,4,0,4))
                .addLast(new LengthFieldPrepender(4))
                .addLast("cryptCodec", new CryptMsgPackCodec())
                .addLast("msgPackDecoder",new MsgPackDecoder())
                .addLast("msgPackEncoder",new MsgPackEncoder())
                .addLast("PlainMsgCodec", plainMsgCodec)
                .addLast("fileCodec", fileMsgCodec)        .addLast(new ChannelInboundHandlerAdapter(){
            @Override
            public void channelActive(ChannelHandlerContext ctx) throws Exception {
                // 通过通道对端的IP地址，获取传输节点
                InetSocketAddress address = (InetSocketAddress)ctx.channel().remoteAddress();
                String peerAddr = address.getAddress().getHostAddress();
                SysDept sysDept = sysDeptService.selectDeptByAddr(peerAddr);
                CommVars.nodeKcpChannel.put(sysDept.getDeptId(), ctx.channel());
            }

            @Override
            public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
                // todo
//                cause.getCause() instanceof  .
                InetSocketAddress address = (InetSocketAddress)ctx.channel().remoteAddress();
                String peerAddr = address.getAddress().getHostAddress();
                log.error("【Channel】{}-peerAddr:{}出错，ErrMsg:{}", ctx.channel().id(), peerAddr, cause.getLocalizedMessage());
                if(!ctx.channel().isActive()){
                    NodeQueue.remove(peerAddr);
                    ctx.channel().close();
                }
//                super.exceptionCaught(ctx, cause);
            }
        });
    }
}
